java DataBaseExecutor

package com.icss.core.db;

import com.icss.core.util.UUIDGenerator;
import com.icss.core.util.format.ValueObjectFormat;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class DataBaseExecutor
{
  protected Connection m_conn = null;

  public static DataBaseExecutor getExecutor(Connection conn) {
    DataBaseExecutor executor = null;
    int dbtype = DataBaseType.getConnectionDBType(conn);
    switch (dbtype) {
    case 1:
      executor = new OracleDataBaseExecutor(conn); break;
    case 8:
      executor = new AccessDataBaseExecutor(conn); break;
    case 0:
      break;
    default:
      throw new RuntimeException("unsupported db type!");
    }
    return executor;
  }
  protected DataBaseExecutor(Connection conn) {
    this.m_conn = conn;
  }
  public Connection getConnection() { return this.m_conn;
  }

  public int create(RecordSet recordSet)
    throws SQLException
  {
    for (int i = 0; i < recordSet.size(); i++)
    {
      create(recordSet.get(i));
    }
    return recordSet.size();
  }

  protected int create(Record record)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    try
    {
      fullPrimaryKeyValueWithUuid(record);

      StringBuffer sb = new StringBuffer("INSERT INTO ");
      sb.append(record.getEntityName()).append(" ( ");
      StringBuffer placeholderBuffer = new StringBuffer();
      String[] fields = record.getFields();
      for (int i = 0; i < fields.length; i++)
      {
        if (i > 0)
        {
          sb.append(",");
          placeholderBuffer.append(",");
        }
        sb.append(fields[i]);
        placeholderBuffer.append("?");
      }
      sb.append(" ) VALUES ( ").append(placeholderBuffer).append(" )");
      pstmt = this.m_conn.prepareStatement(sb.toString());
      Map entryColumnTypeCode = getEntryColumnTypeCode(record.getEntityName());
      setPreparedStatementParameter(pstmt, record.getFields(), 1, entryColumnTypeCode, record);
      int i = pstmt.execute() ? 1 : 0;
      return i;
    }
    catch (SQLException e)
    {
      throw e;
    }
    finally
    {
      try
      {
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException2) {
      }
    }
    throw localObject;
  }

  protected int update(Record record)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    try
    {
      String[] fields = record.getFields();
      String[] primaryKeyFields = record.getPrimaryKeyFields();
      String[] fieldsExceptPK = new String[fields.length - primaryKeyFields.length];
      StringBuffer sb = new StringBuffer("UPDATE ");
      sb.append(record.getEntityName()).append(" SET ");
      int i = 0; for (int j = 0; i < fields.length; i++)
      {
        String field = fields[i];
        if (record.containsPrimaryKey(field))
          continue;
        if (j > 0)
        {
          sb.append(",");
        }
        sb.append(fields[i]);
        sb.append("=?");
        fieldsExceptPK[(j++)] = field;
      }

      sb.append(" WHERE 1=1 ");
      for (int i = 0; i < primaryKeyFields.length; i++)
      {
        String pk = primaryKeyFields[i];
        Object pkValue = record.getObjectValue(pk);
        if ((pkValue == null) || ("".equals(pkValue)) || ("null".equals(pkValue)))
        {
          throw new DBException("some of the key column is not evaluated, the column name is " + pk);
        }

        sb.append("AND ");
        sb.append(pk);
        sb.append("=? ");
      }

      pstmt = this.m_conn.prepareStatement(sb.toString());
      Map entryColumnTypeCode = getEntryColumnTypeCode(record.getEntityName());
      setPreparedStatementParameter(pstmt, fieldsExceptPK, 1, entryColumnTypeCode, record);
      setPreparedStatementParameter(pstmt, primaryKeyFields, fieldsExceptPK.length + 1, entryColumnTypeCode, record);
      int i = pstmt.executeUpdate();
      return i;
    }
    finally
    {
      try
      {
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject1;
  }

  public int update(RecordSet recordSet)
    throws SQLException
  {
    for (int i = 0; i < recordSet.size(); i++)
    {
      update(recordSet.get(i));
    }
    return recordSet.size();
  }

  public int delete(RecordSet recordSet)
    throws SQLException
  {
    for (int i = 0; i < recordSet.size(); i++)
    {
      delete(recordSet.get(i));
    }
    return recordSet.size();
  }

  protected int delete(Record record)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    try
    {
      String[] primaryKeyFields = record.getPrimaryKeyFields();
      StringBuffer sb = new StringBuffer("DELETE FROM ");
      sb.append(record.getEntityName());

      sb.append(" WHERE ");
      if (primaryKeyFields.length == 0)
      {
        throw new DBException("you must specify one column as the primary key at least ");
      }
      for (int i = 0; i < primaryKeyFields.length; i++)
      {
        String pk = primaryKeyFields[i];
        Object pkValue = record.getObjectValue(pk);
        if ((pkValue == null) || ("".equals(pkValue)) || ("null".equals(pkValue)))
        {
          throw new DBException("some of the key column is not evaluated, the column name is " + pk);
        }

        if (i > 0)
        {
          sb.append(" AND ");
        }
        sb.append(pk);
        sb.append("=?");
      }

      pstmt = this.m_conn.prepareStatement(sb.toString());
      Map entryColumnTypeCode = getEntryColumnTypeCode(record.getEntityName());
      setPreparedStatementParameter(pstmt, primaryKeyFields, 1, entryColumnTypeCode, record);
      int i = pstmt.executeUpdate();
      return i;
    }
    finally
    {
      try
      {
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject1;
  }

  public int delete(String entryName, String fieldName, List values)
  {
    return 0;
  }

  public int execute(String sql)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    try
    {
      pstmt = this.m_conn.prepareStatement(sql);
      int i = pstmt.executeUpdate();
      return i;
    }
    finally
    {
      try
      {
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  public Record findFirst(String sql)
    throws SQLException
  {
    RecordSet recs = find(sql);
    return (recs != null) && (recs.size() > 0) ? recs.get(0) : null;
  }

  public RecordSet find(String sql)
    throws SQLException
  {
    RecordSet records = new RecordSet();
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try
    {
      pstmt = this.m_conn.prepareStatement(sql);
      rs = pstmt.executeQuery();
      ResultSetMetaData rsmd = rs.getMetaData();
      Map entryColumnType = getEntryColumnType(rsmd);

      while (rs.next())
      {
        Record record = fillRecord(rs, rsmd, entryColumnType);
        records.add(record);
      }
      RecordSet localRecordSet1 = records;
      return localRecordSet1;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  public RecordSet find(String sql, PagingInfo pagingInfo)
    throws SQLException
  {
    List selectColumnList = getFieldsFromSqlStatment(sql);
    StringBuffer selectedFields = new StringBuffer("");
    for (int i = 0; i < selectColumnList.size(); i++)
    {
      selectedFields.append((String)selectColumnList.get(i));
      selectedFields.append(",");
    }
    selectedFields.setCharAt(selectedFields.length() - 1, ' ');

    int iPageSize = pagingInfo.getPageSize();
    int iPageNo = pagingInfo.getCurrentPageNo();

    int iRecordCount = getRecordTotalCount(sql);
    pagingInfo.setTotalRecordCount(iRecordCount);

    StringBuffer sb = new StringBuffer();
    sb.append("SELECT ").append(selectedFields).append(" FROM (");
    sb.append("SELECT TBL.*,ROWNUM RN FROM (");
    sb.append(sql);
    sb.append(")TBL WHERE ROWNUM <= ").append(iPageNo * iPageSize);
    sb.append(") WHERE RN > ").append((iPageNo - 1) * iPageSize);
    return find(sb.toString());
  }

  private int getRecordTotalCount(String sql) throws SQLException
  {
    StringBuffer sb = new StringBuffer();
    sb.append("SELECT COUNT(1) AS CC FROM (");
    sb.append(sql);
    sb.append(") ");

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try
    {
      pstmt = this.m_conn.prepareStatement(sb.toString());
      rs = pstmt.executeQuery();
      int i = rs.next() ? rs.getInt("CC") : 0;
      return i;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  protected RecordSet find(Record record, String[] columns, String[] order, PagingInfo pagingInfo) throws SQLException
  {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    RecordSet records = new RecordSet();
    try
    {
      String[] conditionFields = record.getFields();
      String sql = buildSql4FindByRecord(record, columns, conditionFields, order);
      pstmt = this.m_conn.prepareStatement(sql);

      Map entryColumnTypeCode = getEntryColumnTypeCode(record.getEntityName());
      setPreparedStatementParameter(pstmt, conditionFields, 1, entryColumnTypeCode, record);

      rs = pstmt.executeQuery();
      ResultSetMetaData rsmd = rs.getMetaData();
      Map entryColumnType = getEntryColumnType(rsmd);
      while (rs.next())
      {
        Record newRecord = fillRecord(rs, rsmd, entryColumnType);
        records.add(newRecord);
      }
      RecordSet localRecordSet1 = records;
      return localRecordSet1;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  protected RecordSet findAll(Record record, String[] columns, String[] order)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    RecordSet records = new RecordSet();
    try
    {
      String sql = buildSql4FindByRecord(record, columns, null, order);
      pstmt = this.m_conn.prepareStatement(sql);
      rs = pstmt.executeQuery();
      ResultSetMetaData rsmd = rs.getMetaData();
      Map entryColumnType = getEntryColumnType(rsmd);
      while (rs.next())
      {
        Record newRecord = fillRecord(rs, rsmd, entryColumnType);
        records.add(newRecord);
      }
      RecordSet localRecordSet1 = records;
      return localRecordSet1;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  protected Record findByPrimaryKey(Record record, String[] selectFields)
    throws SQLException
  {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try
    {
      String[] primaryKeyFields = record.getPrimaryKeyFields();
      String sql = buildSql4FindByRecord(record, selectFields, primaryKeyFields, null);
      pstmt = this.m_conn.prepareStatement(sql);
      Map entryColumnTypeCode = getEntryColumnTypeCode(record.getEntityName());
      setPreparedStatementParameter(pstmt, primaryKeyFields, 1, entryColumnTypeCode, record);
      rs = pstmt.executeQuery();
      ResultSetMetaData rsmd = rs.getMetaData();
      Map entryColumnType = getEntryColumnType(rsmd);
      Record ret = null;
      if (rs.next())
      {
        ret = fillRecord(rs, rsmd, entryColumnType);
      }
      Record localRecord1 = ret;
      return localRecord1;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (pstmt != null)
        {
          pstmt.close();
        }
      }
      catch (SQLException localSQLException1) {
      }
    }
    throw localObject;
  }

  protected void fullPrimaryKeyValueWithUuid(Record record)
  {
    Iterator pkIterator = record.primaryKeyIterator();
    while (pkIterator.hasNext())
    {
      String pk = (String)pkIterator.next();
      Object pkValue = record.getObjectValue(pk);
      if ((pkValue != null) && (!"".equals(pkValue)) && (!"null".equals(pkValue)))
        continue;
      record.addData(pk, UUIDGenerator.getUUID());
    }
  }

  protected void setPreparedStatementParameter(PreparedStatement pstmt, String[] fields, int baseParamIndex, Map<String, Integer> entryColumnTypeCode, Record record)
    throws SQLException
  {
    for (int i = 0; i < fields.length; i++)
    {
      String columnName = fields[i];
      Object columnValue = record.getObjectValue(columnName);
      ValueObjectFormat formatter = ValueObjectFormat.getFormat(columnValue);
      Integer columnTypeCode = (Integer)entryColumnTypeCode.get(columnName);
      if (columnTypeCode == null) throw new RuntimeException("the column " + columnName + " is undefined,please check it and try again.");
      setPreparedStatementParameter(pstmt, i + baseParamIndex, columnTypeCode.intValue(), columnValue, formatter);
    }
  }

  protected Map<String, String> getEntryColumnType(String entryName) throws SQLException
  {
    PreparedStatement ps = null;
    ResultSet rs = null;
    try
    {
      StringBuffer sb = new StringBuffer("SELECT * FROM ").append(entryName).append(" WHERE 1=2");
      ps = this.m_conn.prepareStatement(sb.toString());
      rs = ps.executeQuery();
      Map localMap = getEntryColumnType(rs.getMetaData());
      return localMap;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (ps != null)
        {
          ps.close();
        }
      }
      catch (Exception localException1) {
      }
    }
    throw localObject;
  }

  protected Map<String, String> getEntryColumnType(ResultSetMetaData rsmd) throws SQLException
  {
    Map retMap = new HashMap();
    for (int i = 1; i <= rsmd.getColumnCount(); i++)
    {
      retMap.put(rsmd.getColumnName(i).toUpperCase(), rsmd.getColumnClassName(i));
    }
    return retMap;
  }

  protected Map<String, Integer> getEntryColumnTypeCode(String entryName) throws SQLException
  {
    PreparedStatement ps = null;
    ResultSet rs = null;
    try
    {
      StringBuffer sb = new StringBuffer("SELECT * FROM ").append(entryName).append(" WHERE 1=2");
      ps = this.m_conn.prepareStatement(sb.toString());
      rs = ps.executeQuery();

      Map retMap = new HashMap();
      ResultSetMetaData rsmd = rs.getMetaData();
      for (int i = 1; i <= rsmd.getColumnCount(); i++)
      {
        retMap.put(rsmd.getColumnName(i).toUpperCase(), Integer.valueOf(rsmd.getColumnType(i)));
      }
      Map localMap1 = retMap;
      return localMap1;
    }
    finally
    {
      try
      {
        if (rs != null)
        {
          rs.close();
        }
        if (ps != null)
        {
          ps.close();
        }
      }
      catch (Exception localException1) {
      }
    }
    throw localObject;
  }

  protected abstract void setPreparedStatementParameter(PreparedStatement paramPreparedStatement, int paramInt1, int paramInt2, Object paramObject, ValueObjectFormat paramValueObjectFormat) throws SQLException;

  protected abstract Record fillRecord(ResultSet paramResultSet, ResultSetMetaData paramResultSetMetaData, Map<String, String> paramMap) throws SQLException;

  private String buildSql4FindByRecord(Record record, String[] selectFields, String[] conditionFields, String[] order) {
    StringBuffer sb = new StringBuffer("SELECT ");
    if ((selectFields == null) || (selectFields.length == 0))
    {
      sb.append(" * ");
    }
    else
    {
      for (int i = 0; i < selectFields.length; i++)
      {
        sb.append(selectFields[i]);
        sb.append(",");
      }
      sb.setCharAt(sb.length() - 1, ' ');
    }
    sb.append(" FROM ");
    sb.append(record.getEntityName());

    if (conditionFields != null)
    {
      sb.append(" WHERE 1=1 ");
      if (conditionFields.length == 0)
      {
        throw new DBException("you do not set the search condition, at least one condition column was specified!");
      }
      for (int i = 0; i < conditionFields.length; i++)
      {
        String column = conditionFields[i];
        Object pkValue = record.getObjectValue(column);
        if ((pkValue == null) || ("".equals(pkValue)) || ("null".equals(pkValue)))
        {
          throw new DBException("some of the condition column is not evaluated, the column name is " + column);
        }

        sb.append("AND ");
        sb.append(column);
        sb.append("=? ");
      }
    }

    if (order != null)
    {
      sb.append(" ORDER BY ");
      for (int i = 0; i < order.length; i++)
      {
        sb.append(order[i]).append(",");
      }
      sb.setCharAt(sb.length() - 1, ' ');
    }
    return sb.toString();
  }

  private List<String> getFieldsFromSqlStatment(String sql)
  {
    List fields = new ArrayList();

    String s = sql;
    Matcher m = null;

    Pattern parenthesis_pattern = Pattern.compile("\\([^\\(\\)]*\\)");
    while (parenthesis_pattern.matcher(s).find())
    {
      s = s.replaceAll("\\([^\\(\\)]*\\)", " ");
    }

    Pattern select_pattern = Pattern.compile("\\s*SELECT\\s+(.*?\\s+FROM)\\s+.*", 2);
    m = select_pattern.matcher(s);
    if (m.find())
    {
      s = m.group(1);
    }

    Pattern fields_pattern = Pattern.compile("\\s*([^\\s\\.]*)\\s*(,|FROM)", 2);
    m = fields_pattern.matcher(s);
    while (m.find())
    {
      fields.add(m.group(1));
    }

    return fields;
  }
}

posted @ 2012-06-26 17:45  Brook Legend  阅读(325)  评论(0编辑  收藏  举报